﻿#region Using Statements
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
#endregion

using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.IO;

using projetSupinfoBFG.Screens;
using projetSupinfoBFG.Base;
using projetSupinfoBFG.Base.Model;

namespace projetSupinfoBFG.Screens
{
    class LevelScreen : GameScreen
    {
        #region Fields

        ContentManager content;
        Texture2D backgroundTexture;
        Game game;
        #endregion

        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        MapManager level;

        // We store our input states so that we only poll once per frame, 
        // then we use the same input state wherever needed
        private GamePadState gamePadState;
        private KeyboardState keyboardState;

        private SpriteFont hudFont;

        SoundEffectInstance bipAlert;
        private static readonly TimeSpan WarningTime = TimeSpan.FromSeconds(20);
        private SoundEffect BipAltert;

        private int levelIndex = 0;




        int Affdes;


        #region Sprite

        ShipTestSprite testtank;

        #endregion





        ///TANKSSSSSSSSS////////
        ///////

        Vector2 TankPosition = new Vector2(60, 80);
        Vector2 TankOriginPoint;

        Vector2 DecalAlpha = new Vector2(8, 8);

        Vector2 TankVelocity = new Vector2(1, 1);
        float CanonRotation = 40.0f;
        float TankRotation = 0.0f;

        MouseState currentMouseState;
        MouseState lastMouseState;

        Texture2D tank;
        Texture2D canon;




        #region ini

        /// <summary>
        /// Constructor.
        /// </summary>
        public LevelScreen(Game game)
        {
            TransitionOnTime = TimeSpan.FromSeconds(0.5);
            TransitionOffTime = TimeSpan.FromSeconds(0.5);
            this.game = game;
        }

        /// <summary>
        /// Init the sprites
        /// </summary>
        public override void Initialize()
        {
            testtank = new ShipTestSprite(new Vector2(60, 80));
            
        }


        /// <summary>
        /// Loads graphics content for this screen. The background texture is quite
        /// big, so we use our own local ContentManager to load it. This allows us
        /// to unload before going from the menus into the game itself, wheras if we
        /// used the shared ContentManager provided by the Game class, the content
        /// would remain loaded forever.
        /// </summary>
        public override void LoadContent()
        {
            //Initialize Game Screen & Sprite
            Initialize();

            //Load Sprite Content
            testtank.LoadContent("tank_body");





           


            //OLD

            

            if (content == null)
                content = new ContentManager(ScreenManager.Game.Services, "Content");

            //////TANKKSSSSS
            /////
            this.tank = content.Load<Texture2D>("tank_body");
            TankOriginPoint = new Vector2(tank.Width / 2, tank.Height / 2);
            this.canon = content.Load<Texture2D>("tank_canon");



            backgroundTexture = content.Load<Texture2D>("Backgrounds/fond_mainmenu");

            hudFont = content.Load<SpriteFont>("Fonts/Gothic-Elfic-Font");
            BipAltert = content.Load<SoundEffect>("Sounds/UIerror1");
            bipAlert = BipAltert.CreateInstance();


            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(ScreenManager.Game.GraphicsDevice);




            //load du level
            string levelPath = string.Format("Content/Levels/{0}.txt", levelIndex);
            using (Stream fileStream = TitleContainer.OpenStream(levelPath))
            level = new MapManager(ScreenManager.Game.Services, fileStream, levelIndex);    


        }


        /// <summary>
        /// Unloads graphics content for this screen.
        /// </summary>
        public override void UnloadContent()
        {
            content.Unload();
        }


        #endregion

        #region Update and Draw


        /// <summary>
        /// Updates the background screen. Unlike most screens, this should not
        /// transition off even if it has been covered by another screen: it is
        /// supposed to be covered, after all! This overload forces the
        /// coveredByOtherScreen parameter to false in order to stop the base
        /// Update method wanting to transition off.
        /// </summary>
        public override void Update(GameTime gameTime, bool otherScreenHasFocus,
                                                       bool coveredByOtherScreen)
        {

            //testtank.Rotation += 0.1f;

            testtank.Update();
            level.Update(gameTime, keyboardState, gamePadState, ScreenManager.Game.Window.CurrentOrientation);

            HandleInput();
            Mouvement();
            move_dice();
            base.Update(gameTime, otherScreenHasFocus, false);
        }


        private void HandleInput()
        {
            // get all of our input states
            keyboardState = Keyboard.GetState();
            gamePadState = GamePad.GetState(PlayerIndex.One);


            // Fin du "tour" quand escape est pressé
            if (keyboardState.IsKeyDown(Keys.Escape)) { //Exit(); 
            }
            if (keyboardState.IsKeyDown(Keys.NumPad0) ||
                keyboardState.IsKeyDown(Keys.RightShift) ||
                 keyboardState.IsKeyDown(Keys.LeftShift))
            {
                // level.OnFire(spriteBatch);
            }

            if (keyboardState.IsKeyDown(Keys.Space))
            {
                if ( game.graphics.IsFullScreen)
                {
                    game.graphics.IsFullScreen = false;
                }
                else
                {
                    game.graphics.IsFullScreen = true;
                }
                game.graphics.ApplyChanges();
            }
        }


        private void move_dice()
        {
            ////Dice
            int Resdes = new int();
            Random des = new Random();
            Resdes = des.Next(6);

            if (currentMouseState.RightButton == ButtonState.Released & lastMouseState.RightButton == ButtonState.Pressed)
            {

                Resdes = des.Next(6);
                if (Resdes == 0)
                {
                    Affdes = 1;
                }
                else if (Resdes == 1)
                {
                    Affdes = 2;
                }
                else if (Resdes == 2)
                {
                    Affdes = 3;
                }
                else if (Resdes == 3)
                {
                    Affdes = 4;
                }
                else if (Resdes == 4)
                {
                    Affdes = 5;
                }
                else if (Resdes == 5)
                {
                    Affdes = 6;
                }

            }
        }

        private void Mouvement()
        {
            
            ///TANKSSSS
            TankVelocity = Vector2.Zero;         
            int TankMaximunSpeed = 2;

            float FloatRotation;
            float FloatTank;

            lastMouseState = currentMouseState;
            currentMouseState = Mouse.GetState();

            if (currentMouseState.LeftButton == ButtonState.Pressed)
            {
                Vector2 PositionMouse = new Vector2(currentMouseState.X, currentMouseState.Y);
                TankVelocity = PositionMouse - TankPosition;
                TankVelocity.Normalize();
                TankVelocity *= TankMaximunSpeed;

                FloatRotation = (float)Math.Atan2(PositionMouse.X, PositionMouse.Y);
                FloatTank = (float)Math.Atan2(TankOriginPoint.X, TankOriginPoint.Y);


                if (FloatRotation > FloatTank & FloatRotation != FloatTank)
                {
                    TankRotation += (FloatRotation);
                }
                if (FloatRotation < FloatTank & FloatRotation != FloatTank)
                {
                    TankRotation -= (FloatRotation);                
                }


            }

            
            Vector2 TankUpLeft = TankPosition - TankOriginPoint + DecalAlpha;
            Vector2 TankDownRight = TankPosition + TankOriginPoint - DecalAlpha;

            if ((TankUpLeft.X <= 0 && TankVelocity.X < 0) || (TankDownRight.X >= ScreenManager.Game.GraphicsDevice.Viewport.Width && TankVelocity.X > 0))
                TankVelocity.X = 0;

            if ((TankUpLeft.Y <= 0 && TankVelocity.Y < 0) || (TankDownRight.Y >= ScreenManager.Game.GraphicsDevice.Viewport.Height && TankVelocity.Y > 0))
                TankVelocity.Y = 0;
            /*1e jey de gestion des collisions. Il manque la prise en compte de la taille de l'obstacle, 
             * la taille du vehicule et une gestion plus propre pour ne pas etre bloquer quand on recule*/
            ObstacleCollision obs;
            obs = level.GetCollision((int)TankPosition.X, (int)TankPosition.Y);
            if (obs == 0)
            {
                TankPosition += TankVelocity;
            }
            else
            {
                TankPosition -= TankVelocity;
            }
            
        }

        /// <summary>
        /// Draws the background screen.
        /// </summary>
        public override void Draw(GameTime gameTime)
        {
            ScreenManager.Game.GraphicsDevice.Clear(Color.CornflowerBlue);
            spriteBatch.Begin();
            level.Draw(gameTime, spriteBatch);
            DrawHud();
            DrawTank();
            testtank.Draw(spriteBatch);
            Drawice();
            spriteBatch.End();
            base.Draw(gameTime);
        }

        private void DrawTank()
        {
            spriteBatch.Draw(this.tank, TankPosition, null, Color.White, MathHelper.ToRadians(TankRotation), TankOriginPoint, 1.0f, SpriteEffects.None, 0);
            spriteBatch.Draw(this.canon, TankPosition, null, Color.White, CanonRotation, new Vector2(canon.Width / 2 - 4.0f, canon.Height / 2), 1.0f, SpriteEffects.None, 0);

        }

        private void Drawice()
        {
            string text1 = string.Format("Jet de des : {0} ", this.Affdes);
            spriteBatch.DrawString(this.hudFont, text1, new Vector2(10, 5), Color.Red);
        }

        private void DrawHud()
        {
            Rectangle titleSafeArea = ScreenManager.Game.GraphicsDevice.Viewport.TitleSafeArea;
            Vector2 hudLocation = new Vector2(titleSafeArea.X+10, titleSafeArea.Height - 50);
            Vector2 center = new Vector2(titleSafeArea.X + titleSafeArea.Width / 2.0f,
                                         titleSafeArea.Y + titleSafeArea.Height / 2.0f);

            // Draw time remaining. Uses modulo division to cause blinking when the
            // player is running out of time.
            string timeString = "TIME: " + level.TimeRemaining.Minutes.ToString("00") + ":" + level.TimeRemaining.Seconds.ToString("00");
            Color timeColor;
            if (level.TimeRemaining > WarningTime ||
                (int)level.TimeRemaining.TotalSeconds % 2 == 0)
            {
                timeColor = Color.WhiteSmoke;
            }
            else
            {
                timeColor = Color.Red;
            }
            if (level.TimeRemaining < TimeSpan.FromSeconds(10))
            {
                if (bipAlert.State != SoundState.Playing)
                {
                    bipAlert.Play();
                }
            }
            DrawShadowedString(hudFont, timeString, hudLocation, timeColor);

            // Draw score
            float timeHeight = hudFont.MeasureString(timeString).Y;
            // DrawShadowedString(hudFont, "SCORE: " + level.Score.ToString(), hudLocation + new Vector2(0.0f, timeHeight * 1.2f), Color.Yellow);

            // Determine the status overlay message to show.
            Texture2D status = null;
            if (level.TimeRemaining == TimeSpan.Zero)
            {

            }
            if (status != null)
            {
                // Draw status message.
                Vector2 statusSize = new Vector2(status.Width, status.Height);
                spriteBatch.Draw(status, center - statusSize / 2, Color.White);
            }
        }

        private void DrawShadowedString(SpriteFont font, string value, Vector2 position, Color color)
        {
            spriteBatch.DrawString(font, value, position + new Vector2(1.0f, 1.0f), Color.Black);
            spriteBatch.DrawString(font, value, position, color);
        }


        #endregion




    }
}
